#pragma once
#include <iostream>
#include <string>
#include <pthread.h>
#include <functional>
#include <sys/types.h>
#include <unistd.h>

namespace ThreadModule
{
    using func_t = std::function<void(std::string name)>;

    static int number = 1;
    enum class TSTATUS
    {
        NEW,
        RUNNING,
        STOP
    };
    class Thread
    {
    private:
        static void *Routine(void *args)
        {
            //显示类型转换
            Thread* t = static_cast<Thread *>(args);
            t->_status = TSTATUS::RUNNING;
            t->_func(t->_name);
            return nullptr;
        }
        void EnableDetach() {_joinable = false; }
    public:
        Thread(func_t func)
            : _func(func)
            , _status(TSTATUS::NEW)
            , _joinable(true)
        {
            _name = "Thread-" + std::to_string(number++);
            _pid = getpid();
        }
        bool Start()
        {
            if(_status != TSTATUS::RUNNING)
            {
                int n = ::pthread_create(&_tid, nullptr, Routine, this);
                if(n != 0)
                    return false;
                return true;
            }
            return true;
        }
        bool Stop()
        {
            if(_status == TSTATUS::RUNNING)
            {
                int n = ::pthread_cancel(_tid);
                if(n != 0)
                    return false;
                _status = TSTATUS::STOP;
                return true;
            }
            return false;
        }
        bool Join()
        {
            if(_joinable)
            {
                int n = ::pthread_join(_tid, nullptr);
                if(n != 0)
                    return false;
                _status = TSTATUS::STOP;
                return true;
            }
            return true;
        }
        void Detach()
        {
            EnableDetach();
            pthread_detach(_tid);
        }
        bool IsJoinable() {return _joinable; }
        std::string Name() {return _name; }
        ~Thread(){}
    private:
        std::string _name; //线程名字
        pthread_t _tid; //线程tid
        pid_t _pid; //进程pid
        bool _joinable; //是否可以等待
        func_t _func;
        TSTATUS _status;
    };
}
